/* 
 * %W% %E% Enrique Madrid
 *
 * Copyright (c) 1975-2008 M&T Consulting, Inc. All rights Reserved.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public
 * License along with this program; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */


package com.myt.tools.obtk.openbravo.account;

import java.io.*;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.FactoryConfigurationError;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.Element;
import org.w3c.dom.Text;
import org.w3c.dom.NodeList;


import javax.xml.transform.TransformerFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

//import org.apache.crimson.tree.XmlDocument;

public class Chart {

    public static final int CHA_FMT_CSV = 1;
    public static final int CHA_FMT_XML = 2;

    private String filename = "default.csv";
    private int filetype = CHA_FMT_CSV;

    Document documentXML = null;

    protected Chart() {
    }

    public static Chart newInstance() {
	Chart c = new Chart();
	if (c.makeDocument() == null) {
	    c = null;
	}
	return c;
    }

    private void setFileAttr(String name, int type) {
	filename = name;
	filetype = CHA_FMT_CSV;
    }

    protected Document makeDocument() {

	documentXML = null;

	try {
	    DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
	    DocumentBuilder db = dbf.newDocumentBuilder();
	    documentXML = db.newDocument();
	    // Node Type
	    Element xmlChart = documentXML.createElement("CHART");
	    documentXML.appendChild(xmlChart);
	    // Node Name
	    Element xmlField = documentXML.createElement("Name");
	    xmlField.appendChild(documentXML.createTextNode("COA Name"));
	    xmlChart.appendChild(xmlField);
	    return documentXML;
	} catch (Exception e) {
	    System.out.printf("\tException: %s\n", e.getMessage());
	    System.out.printf("\tClass    : %s\n", e.getClass());
	    return null;
	}
    }

    protected Element makeXMLAccount(Account ac) {
	Element xmlAccount;
	Element xmlField;
	try {
	    // ACCOUNT
	    xmlAccount = documentXML.createElement("ACCOUNT");
	    // Value
	    xmlField = documentXML.createElement("Value");
	    xmlField.appendChild(documentXML.createTextNode(ac.toStringValue()));
	    xmlAccount.appendChild(xmlField);
	    // Name
	    xmlField = documentXML.createElement("Name");
	    xmlField.appendChild(documentXML.createTextNode(ac.toStringName()));
	    xmlAccount.appendChild(xmlField);
	    // Description
	    xmlField = documentXML.createElement("Description");
	    xmlField.appendChild(documentXML.createTextNode(ac.toStringDescription()));
	    xmlAccount.appendChild(xmlField);
	    // Type
	    xmlField = documentXML.createElement("Type");
	    xmlField.appendChild(documentXML.createTextNode(ac.toStringType()));
	    xmlAccount.appendChild(xmlField);
	    // Sign
	    xmlField = documentXML.createElement("Sign");
	    xmlField.appendChild(documentXML.createTextNode(ac.toStringSign()));
	    xmlAccount.appendChild(xmlField);
	    // Documment
	    xmlField = documentXML.createElement("Document");
	    xmlField.appendChild(documentXML.createTextNode(ac.toStringIsDocument()));
	    xmlAccount.appendChild(xmlField);
	    // Summary
	    xmlField = documentXML.createElement("Summary");
	    xmlField.appendChild(documentXML.createTextNode(ac.toStringIsSummary()));
	    xmlAccount.appendChild(xmlField);
	    // Account
	    xmlField = documentXML.createElement("Account");
	    xmlField.appendChild(documentXML.createTextNode(ac.toStringAccount()));
	    xmlAccount.appendChild(xmlField);
	    // Parent
	    xmlField = documentXML.createElement("Parent");
	    xmlField.appendChild(documentXML.createTextNode(ac.toStringParent()));
	    xmlAccount.appendChild(xmlField);
	    // Level
	    xmlField = documentXML.createElement("Level");
	    xmlField.appendChild(documentXML.createTextNode(ac.toStringLevel()));
	    xmlAccount.appendChild(xmlField);
	    // Operands
	    xmlField = documentXML.createElement("Operands");
	    xmlField.appendChild(documentXML.createTextNode(ac.toStringOperands()));
	    xmlAccount.appendChild(xmlField);
	} catch (Exception e) {
	    xmlAccount = null;
	}

	return xmlAccount;
    }

    public boolean load(String filename, int type) {
	boolean ret = false;

	switch (type) {
	case CHA_FMT_CSV:
	    ret = loadFromCSV(filename);
	    break;
	case CHA_FMT_XML:
	    ret = loadFromXML(filename);
	    break;
	}

	if (ret) {
	    setFileAttr(filename, type);
	}

	return ret;
    }

    public boolean loadFromXML(String filename) {

	return false;
    }

    public boolean loadFromCSV(String filename) {
	FileReader fileInput = null;
	boolean ret = true;

	try {
	    System.out.printf("Loading Chart Of Account from %s ...\n", filename);
	    fileInput = new FileReader(filename);
	    LineNumberReader reader = new LineNumberReader(fileInput);
	    String line = reader.readLine();
	    while (line != null) {
		Account ac = appendAccount(line);
		if (ac == null) {
		    System.out.println("Unkown Openbravo Chart of Accounts comma separated value file format!");
		    ret = false;
		    break;
		}
		line = reader.readLine();
	    }
	    fileInput.close();
	} catch (FileNotFoundException fnfe) {
	    System.out.printf("File %s not found!\n", filename);
	    ret = false;
	} catch (IOException ioe) {
	    System.out.println("Input error!");
	    ret = false;
	}

	return ret;
    }

    public boolean saveAs(String filename, int type) {
	boolean ret = false;

	switch (type) {
	case CHA_FMT_XML:
	    ret = saveToXML(filename);
	    break;
	case CHA_FMT_CSV:
	    ret = saveToCVS(filename);
	    break;
	}

	if (ret) {
	    setFileAttr(filename, type);
	}

	return ret;
    }

    public boolean saveToCVS(String filename) {
	return false;
    }

//     public boolean saveToXML(String filename) {
// 	boolean ret = false;
// 	try {
// 	    PrintStream ps = new PrintStream(filename);
// 	    System.out.printf("Saving Chart of Accounts to %s\n", filename);
// 	    //((org.apache.crimson.tree.XmlDocument)documentXML).write(ps);
// 	    ps.close();
// 	    ret = true;
// 	} catch (FileNotFoundException fnfe) {
// 	    System.out.printf("File %s not found!\n", filename);
// 	} catch (SecurityException se) {
// 	    System.out.printf("Write access denied on %s!\n", filename);
// 	} catch (IOException e) {
// 	    System.out.println("Error!");
// 	} 

// 	return ret;
//     }

    public boolean saveToXML(String filename) {
	boolean ret = false;
	try {
	    DOMSource source = new DOMSource(documentXML);

	    StreamResult result = new StreamResult(new OutputStreamWriter(
									  new FileOutputStream(filename),
									  "utf-8"));
	    TransformerFactory tf = TransformerFactory.newInstance();
	    tf.setAttribute("indent-number", new Integer(2));
	    Transformer transformer = tf.newTransformer();
	    transformer.setOutputProperty("method", "xml");
	    transformer.setOutputProperty(OutputKeys.INDENT, "yes");
	    System.out.printf("Saving Chart of Axccounts to %s\n", filename);
	    transformer.transform(source, result);
	} catch (FileNotFoundException fnfe) {
	    System.out.printf("File %s not found!\n", filename);
	} catch (SecurityException se) {
	    System.out.printf("Write access denied on %s!\n", filename);
	} catch (Exception e) {
	    System.out.println("Error!");
	} 

	return ret;
    }

    public Account appendAccount(String line) {
	Node parent;
	Node newNode;
	Account ac = Account.newInstance(line);
	if (ac != null) {
	    newNode = makeXMLAccount(ac);
	    parent = searchNode(ac.toStringParent());
	    if (parent == null) {
		parent = documentXML.getDocumentElement();
	    }
	    parent.appendChild(newNode);
	}
	return ac;
    }

    private Node searchNode(String id) {
	Node ret = null;
	Text value = null;
	NodeList list = documentXML.getElementsByTagName("Value");
	for (int i = 0; i < list.getLength(); i++) {
	    value = (Text)list.item(i).getFirstChild();
	    //System.out.printf("value.getFirstChild() = %s, and id = %s\n", value.getWholeText(), id);
	    if (value.getWholeText().equals(id)) {
		ret = (list.item(i)).getParentNode();
		break;
	    }

	}

	return ret;
    }

    public void reValue(String start) {

    }
}